From: David Polakovic Date: Mon, 9 Mar 2026 12:52:51 +0000 (+0100) Subject: feat: Initial commit. X-Git-Tag: 1.0.0 X-Git-Url: https://git.dpolakovic.space/%22%22.esc_url%28%24base_url%29.%22//%22%22/%22%22.esc_url%28%24base_url%29.%22//%22%22?a=commitdiff_plain;h=2b748d43548fd636b5ebaf04e5f68c2f0210f652;p=htcpcp-requestor feat: Initial commit. --- 2b748d43548fd636b5ebaf04e5f68c2f0210f652 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84e4199 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +TO_DO.txt \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..10bc13c --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,127 @@ +The "Artistic License" + + Preamble + +The intent of this document is to state the conditions under which a +Package may be copied, such that the Copyright Holder maintains some +semblance of artistic control over the development of the package, +while giving the users of the package the right to use and distribute +the Package in a more-or-less customary fashion, plus the right to make +reasonable modifications. + +Definitions: + + "Package" refers to the collection of files distributed by the + Copyright Holder, and derivatives of that collection of files + created through textual modification. + + "Standard Version" refers to such a Package if it has not been + modified, or has been modified in accordance with the wishes + of the Copyright Holder as specified below. + + "Copyright Holder" is whoever is named in the copyright or + copyrights for the package. + + "You" is you, if you're thinking about copying or distributing + this Package. + + "Reasonable copying fee" is whatever you can justify on the + basis of media cost, duplication charges, time of people involved, + and so on. (You will not be required to justify it to the + Copyright Holder, but only to the computing community at large + as a market that must bear the fee.) + + "Freely Available" means that no fee is charged for the item + itself, though there may be fees involved in handling the item. + It also means that recipients of the item may redistribute it + under the same conditions they received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications +derived from the Public Domain or from the Copyright Holder. A Package +modified in such a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided +that you insert a prominent notice in each changed file stating how and +when you changed that file, and provided that you do at least ONE of the +following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or + an equivalent medium, or placing the modifications on a major archive + site such as uunet.uu.net, or by allowing the Copyright Holder to include + your modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict + with standard executables, which must also be provided, and provide + a separate manual page for each non-standard executable that clearly + documents how it differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or +executable form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where + to get the Standard Version. + + b) accompany the distribution with the machine-readable source of + the Package with your modifications. + + c) give non-standard executables non-standard names, and clearly + document the differences in manual pages (or equivalent), together + with instructions on where to get the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this +Package. You may not charge a fee for this Package itself. However, +you may distribute this Package in aggregate with other (possibly +commercial) programs as part of a larger (possibly commercial) software +distribution provided that you do not advertise this Package as a +product of your own. You may embed this Package's interpreter within +an executable of yours (by linking); this shall be construed as a mere +form of aggregation, provided that the complete Standard Version of the +interpreter is so embedded. + +6. The scripts and library files supplied as input to or produced as +output from the programs of this Package do not automatically fall +under the copyright of this Package, but belong to whoever generated +them, and may be sold commercially, and may be aggregated with this +Package. If such scripts or library files are aggregated with this +Package via the so-called "undump" or "unexec" methods of producing a +binary executable image, then distribution of such an image shall +neither be construed as a distribution of this Package nor shall it +fall under the restrictions of Paragraphs 3 and 4, provided that you do +not represent such an executable image as a Standard Version of this +Package. + +7. C subroutines (or comparably compiled subroutines in other +languages) supplied by you and linked into this Package in order to +emulate subroutines and variables of the language defined by this +Package shall not be considered part of this Package, but are the +equivalent of input as in Paragraph 6, provided these subroutines do +not change the language in any way that would cause it to fail the +regression tests for the language. + +8. Aggregation of this Package with a commercial distribution is always +permitted provided that the use of this Package is embedded; that is, +when no overt attempt is made to make this Package's interfaces visible +to the end user of the commercial distribution. Such use shall not be +construed as a distribution of this Package. + +9. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + The End \ No newline at end of file diff --git a/get-coffee-from b/get-coffee-from new file mode 100644 index 0000000..014e3ad --- /dev/null +++ b/get-coffee-from @@ -0,0 +1,173 @@ +#!/usr/bin/perl +use strict; +use warnings; +use LWP::UserAgent; +use HTTP::Request; + +# curl -I behaviour: sends HEAD request, returns code +sub head_code { + my ($url) = @_; + + my $ua = LWP::UserAgent->new(max_redirect => 0); + my $req = HTTP::Request->new('HEAD' => $url); + my $res = $ua->request($req); + + return $res->code; +} + +# curl -X behaviour: sends request with specified method, returns code +sub request_code { + my ($method, $url) = @_; + + my $ua = LWP::UserAgent->new(max_redirect => 0); + my $req = HTTP::Request->new(uc($method) => $url); + my $res = $ua->request($req); + + return $res->code; +} + +sub teapot { + print "\nThis server is a teapot.\n"; + print "As per RFC 2324 section 2.3.2: This server is a teapot and refuses to brew coffee.\n"; + print "It may brew tea instead, but coffee is beyond its capabilities.\n"; +} + +# curl -X behaviour: sends request with specified method, returns body +sub request_body { + my ($method, $url) = @_; + + my $ua = LWP::UserAgent->new(max_redirect => 0, timeout => 10); + my $req = HTTP::Request->new(uc($method) => $url); + my $res = $ua->request($req); + + return $res->content; +} + +# find webmaster email in page body +sub find_webmaster_email { + my ($url) = @_; + + my $body = request_body('GET', $url); + return undef unless $body; + + if ($body =~ /mailto:([a-zA-Z0-9._%+\-]+\@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,})/i) { return $1 } + if ($body =~ /webmaster['">\s:]+([a-zA-Z0-9._%+\-]+\@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,})/i) { return $1 } + if ($body =~ /([a-zA-Z0-9._%+\-]+\@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,})/) { return $1 } + + return undef; +} + +sub no_coffee { + my ($host) = @_; + print "This server does not serve any coffee.\n"; + + my $email; + for my $scheme ('https', 'http') { + $email = find_webmaster_email("$scheme://$host/"); + last if $email; + $email = find_webmaster_email("$scheme://$host/contact"); + last if $email; + $email = find_webmaster_email("$scheme://$host/about"); + last if $email; + } + + if ($email) { + print "You can write to its webmaster ($email) and ask them to implement RFC 2324.\n"; + } +} + +sub print_response { + my ($method, $url) = @_; + + my $ua = LWP::UserAgent->new(max_redirect => 0, timeout => 10); + my $req = HTTP::Request->new(uc($method) => $url); + my $res = $ua->request($req); + + # print "Status : " . $res->status_line . "\n"; + # print "Headers:\n" . $res->headers->as_string . "\n"; + print $res->content . "\n" if $res->content; +} + +## meat + +# get the domain +if (scalar(@ARGV) == 0) { + print "Please enter a domain: "; + chomp(my $input = ); + push @ARGV, $input; +} + +if (scalar(@ARGV) != 1) { + die "error: Enter only one domain.\n"; +} + +print "requesting...\n\n"; + +my $arg = $ARGV[0]; + +if ($arg =~ /[^a-zA-Z0-9.\/:]/) { + die "error: This isn't valid url.\n"; +} + +# check if user put www or not +if ($arg !~ /^www\./) { + my $dot_count = () = $arg =~ /\./g; + + # ignore for subdomains + if ($dot_count < 2) { + $arg = "www." . $arg; + } +} + +my $http_domain = "http://" . $arg; +my $https_domain = "https://" . $arg; + +my $http_brew = request_code('BREW', $http_domain); +my $https_brew = request_code('BREW', $https_domain); +my $http_tea = head_code($http_domain . "/teapot"); +my $https_tea = head_code($https_domain . "/teapot"); + +sub good_manners { + my ($protocol) = @_; + + print "Your coffee is served. It's a good manner to refill the beans for others.\n"; + print "Do you want to refill them now? (y/n)"; + chomp(my $answer = ); + + if (lc($answer) eq 'y') { + if ($protocol eq 'http') { + request_code('POST', $http_domain); + print "\nBeans refilled. The pot is ready for the next brew.\n"; + } + if ($protocol eq 'https') { + request_code('POST', $https_domain); + print "\nBeans refilled. The pot is ready for the next brew.\n"; + } + } +} + +# decision tree +if ($http_brew == 200) { + print_response('BREW', $http_domain); + good_manners('http'); +} elsif ($https_brew == 200) { + print_response('BREW', $https_domain); + good_manners('https'); +} elsif ($http_brew == 418 || $https_brew == 418) { + teapot(); +} elsif ($http_tea == 200 || $https_tea == 200) { + teapot(); +} else { + no_coffee(); +} + +#print "\nThank you for using the htcpcp requestor.\n"; + + + +## debuging +# print head_code($http_domain); print "\n"; +# print request_code('BREW', $http_domain); print "\n"; + +# print head_code($https_domain); print "\n"; +# print request_code('BREW', $https_domain); print "\n";